/**
This is the Thrift definition for the Library component
*/
namespace java hydrap2p.library
namespace csharp hydrap2p.library

include "service.thrift"

/** 
Uniquely identifies a object
*/
typedef i64 UID

/**
Stores information about a Range of data
*/
struct Range {
	1:i64 start,
	2:i64 len,
}

/**
Stores information about a hash
*/
struct HashData {
	1:UID uid,		// The UID that this HashData applies to
	2:Range range,	// What data this hash applies to
	3:string algorithm,	// What hash algorithm to use
	4:string hashdata,	// Extra data that means something to this hash algorithm
}

exception InvalidUID {
	1:UID uid,		// the UID that was attempted to access
}

exception FileAlreadyExists {
	1:string path,	// the path and filename that already exists
}

exception FileNotFound {
	1:string path,	// the path and filename that was not found
}

// any other problem accessing files
exception IOProblem {
	1:string path,	// the path and filename that was attempted
	2:string message,
}

/**
Information about a shared object
*/
struct SharedItemInfo {
	1:string name,					// Node name
	2:string pathname,				// Path to node
	3:i64 size,						// How big this item is
	4:bool isDirectory,				// Whether or not node is a directory
	5:UID uid,						// Node ID
	6:map<string, string> metadata,	// Node metadata
	7:map<string, string> extra,	// Extra data associated with this node
	8:bool isShared,				// whether this node is shared
	9:list<HashData> targetHashes,	// A list of hashes that this shared item strives to attain
	10:list<HashData> finishedHashes,	// A list of hashes that this shared item has, generated after it has finished
}

/**
A MetadataChecker is used by the Library to read a file for any extra metadata
*/
service MetadataChecker extends service.Service {
	/**
	Reads the given file for any deep metadata, then returns it
	*/
	map<string, string> parseMetadata(1:string filename) throws (1:FileNotFound e),
}

/**
A HashGenerator is used to hash a file, or a piece of a file
*/
service HashGenerator extends service.Service {
	/**
	Reads the given Shared Item's underlying file data, and returns the hash data for the given Range
	This is intended for use during verifying of a downloaded file
	*/
	string getHash(1:SharedItemInfo target, 2:Range range) throws (1:FileNotFound e),
	/**
	Reads the given Shared Item's underlying file data and return any found hashes
	This is intended for use during scanning of shared directories for shareable files 
	*/
	list<HashData> getHashes(1:SharedItemInfo target) throws (1:FileNotFound e),
	
}

/**
A LibrarySubscriptionType defines what events the listener is interested in receiving
*/
struct LibrarySubscriptionType {
	//Specifies that the listener is interested in any metadata changes to shared objects
	1:bool metadata,
	
	//Specifies that the listener is interested in any changes to downloaded ranges
	2:bool downloadProgress,
	
	//Specifies that the listener is interested in any changes to verified ranges
	3:bool verifiedProgress,
	
	//Specifies that the listener is interested in any new or removed shared objects
	4:bool shared,
}

/**
A LibraryListener is an object that receives updates about shared files
*/
service LibraryListener extends service.Service {
	/**
		Notifies this listener that the shared file has changed its metadata
	*/
	oneway void changedMetadata(1:SharedItemInfo file),
	
	/**
		Notifies this listener that the shared file has changed its extra data
	*/
	oneway void changedExtra(1:SharedItemInfo file),
	
	/**
		Indicates that this shared file has a new downloaded chunk
	*/
	oneway void newPartialProgress(1:SharedItemInfo file, 2:Range range),
	
	/**
		Indicates that this shared file has removed a new downloaded chunk
	*/
	oneway void deletePartialProgress(1:SharedItemInfo file, 2:Range range),
		
	/**
		Indicates that this shared file has a new verified chunk
	*/
	oneway void newVerifiedProgress(1:SharedItemInfo file, 2:Range range),
	
	/**
		Indicates that this shared file has removed a new verified chunk
	*/
	oneway void deleteVerifiedProgress(1:SharedItemInfo file, 2:Range range),
	
	/**
		Notifies this listener than an entirely new shared item has finished hashing and searching metadata
	*/
	oneway void newSharedItem(1:SharedItemInfo file),
	
	/**
		Notifies this listener than an entirely new shared item has finished hashing and searching metadata
	*/
	oneway void removedSharedItem(1:SharedItemInfo file),
}

/**
The main Library interface
*/
service Library extends service.Service {

	/**
		Adds a folder to the Library to be indexed and shared.  
		Returns UID to the newly shared path, or null on error.
	*/
	UID addSharedFolder(1:string path) throws (1:FileNotFound e),

	/**
	Rescan this object for changed metadata and hashes
	Recursively scans if the shared object is a directory
	*/
	void rescan(1:UID uid) throws (1:InvalidUID wronguid),
	
	/**
		Removes a currently shared folder from the Library.  
		Returns true if it was successfully removed.
	*/
	bool removeSharedFolder(1:UID uid) throws (1:InvalidUID wronguid),
	
	/**
		Creates a file at the given location, and will autocreate needed parent paths.  
		Returns UID, or null on error.
	*/
	UID createFile(1:string filename, 2:i64 size) throws (1:FileAlreadyExists e, 2:IOProblem err2),
	
	/**
		Creates a virtual set of files for hashing across files.  
		Returns UID, or null on error.
	*/
	UID createFileSet(1:string name, 2:list<UID> fileUIDs) throws (1:InvalidUID wronguid),
	
	/**
		Gets SharedItemInfo associated with a node UID.
	*/
	SharedItemInfo getSharedItemInfo(1:UID uid) throws (1:InvalidUID wronguid),
	
	/**
		Gets children for a specified node UID.  
		Returns the set of children.
	*/
	list<SharedItemInfo> getChildren(1:UID uid) throws (1:InvalidUID wronguid),
	
	/**
		Gets the downloaded byte ranges of a particular node UID.  
		Returns list of ranges.
	*/
	list<Range> getDownloadedRanges(1:UID uid) throws (1:InvalidUID wronguid),
	
	/**
		Gets the verified byte ranges of a particular node.  
		Returns list of ranges.
	*/
	list<Range> getVerifiedRanges(1:UID uid) throws (1:InvalidUID wronguid),
	
	/**
		Saves bytes into a file at the given offset.  
		Returns true on success.
	*/
	bool saveData(1:UID uid, 2:i64 offset, 3:binary data) throws (1: FileNotFound e, 2:IOProblem err2, 3:InvalidUID wronguid),
	
	/**
		Loads data from a file at the given byte offset.
	*/
	binary loadData(1:UID uid, 2:i64 offset, 3:i32 len) throws (1: FileNotFound e, 2:IOProblem err2, 3:InvalidUID wronguid),
	
	/**
		Subscribes a given LibraryListener to the library. 
		If the listener was already subscribed, the new subscription type will apply
		Returns whether the subscription was successful
	*/
	bool registerListener(1:service.ServiceLocation location, 2:LibrarySubscriptionType subscription),
	
	/**
		Registers a given hash generator for a given algorithm.  Ex. MD5/4, SHA1, etc.
	*/
	bool registerHashGenerator(1:string name, 2:service.ServiceLocation hasher),
	
	/**
		Registers a metadata loader for a specific file extension.
	*/
	bool registerMetadataLoader(1:string fileExtension, 2:service.ServiceLocation location),
	
	/**
		Unsubscribes a given LibraryListener to the library.   
		Returns true if the listener was previous registered.
	*/
	bool unregisterListener(1:service.ServiceLocation location),
	
	/**
		Unregisters a given hash generator for a given algorithm.  
		Returns true if the has generator was previously registered.
	*/
	bool unregisterHashGenerator(1:string name, 2:service.ServiceLocation hasher),
	
	/**
		Unregisters a metadata loader for a specific file extension.  
		Returns true if the metadata loader was previously registered.
	*/
	bool unregisterMetadataLoader(1:string fileExtension, 2:service.ServiceLocation hasher),
	
	/**
		Searches for node filenames containing the query.  
		Returns list of nodes found.
	*/
	list<SharedItemInfo> searchFilename(1:string query),
	
	/**
		Searches for nodes with the given hash.  
		Returns list of nodes found.
	*/
	list<SharedItemInfo> searchHash(1:string algorithm, 2:string hashData),
	
	/**
		Renames the given node.
		Throws an exception if the destination file already exists
	*/
	void setFileName(1:UID uid, 2:string newName) throws (1:FileAlreadyExists e, 2:InvalidUID wronguid),
	
	/**
		Moves the given node to a new path.
		Throws an exception if the destination file already exists
	*/
	void setPathName(1:UID uid, 2:string path) throws (1:FileAlreadyExists e, 2:InvalidUID wronguid),
	
	/**
		Sets the shared status of any node. If [shared] is true, set it to be shared, else don't share it.
		Returns the new shared status.
	*/
	bool setShared(1:UID uid, 2:bool shared) throws (1:InvalidUID wronguid),
	
	/**
		Sets a desired hash for a downloading file, referenced by the given UID, with the hash data applied to a certain length of data starting at offset inside the file. The hash data is identified by a certain algorithm, and an opaque block of hashdata is given to the hash algorithm to verify.
		If the file has the file's data downloaded already, it will check the hash. Otherwise, it will just be remembered for later.
	*/
	void setDownloadHash(1:UID uid, 2:HashData hashdata) throws (1:InvalidUID wronguid),
	
	/**
		Deletes the registered hash data for this range of data on this download
	*/
	void deleteDownloadHash(1:UID uid, 2:HashData hashdata) throws (1:InvalidUID wronguid),

	/**
		Adds the given metadata to a shared file.
		Replaces any existing metadata with the same key.
		Returns true on success.
	*/
	bool setMetadata(1:UID uid, 2:string key, 3:string value) throws (1:InvalidUID wronguid),
	
	/**
		Adds the given metadata to a shared file.
		Replaces any existing metadata with the same key
		Return true if a metadata was deleted
	*/
	bool deleteMetadata(1:UID uid, 2:string key) throws (1:InvalidUID wronguid),
	
	/**
		Sets extra data for a shared object
	*/
	void setExtraData(1:UID uid, 2:string key, 3:string value) throws (1:InvalidUID wronguid),
	
	/**
		Delete the extra data for a share object, corresponding to this key
		Return true if an extra data was deleted
	*/
	bool deleteExtraData(1:UID uid, 2:string key) throws (1:InvalidUID wronguid),
}
